package com.itfenghuang.day12;

import java.util.concurrent.locks.ReentrantLock;

public class 线程安全问题复习 {
    public static void main(String[] args) {
        //
        // 解决线程安全问题
        // 同步代码块 格式 锁对象
        Piao piao = new Piao();
        Thread t1 = new Thread(piao,"窗口1");//重命名当前线路名称
        Thread t2 = new Thread(piao,"窗口2");
        Thread t3 = new Thread(piao,"窗口3");
        t1.start();
        t2.start();
        t3.start();

        //同步代码块解决线路安全问题
        // 类中 添加 private Object obj=new Object();
        //  同步代码块    synchronize(锁对象){ }

        /*  同步方法
        *   格式:  访问修饰符 synchronized 返回值类型 方法名(方法参数){方法体}
        *   解决步骤;
        *      1). 将访问共享数据的代码块抽取出来,放到了一个方法中
        *      2). 在方法上加了一个关键字synchronized
        *      同步方法中的锁对象是哪个对象
        *      this
        */

//        lock锁
//        实现类: ReentrantLock
//        构造方法: public ReentrantLock()
//        public void lock()   加锁
//        public void unlock() 解锁\释放锁*


        //线程死锁
        //由于两个或两个以上的线程互相持有对方所需要的锁,
        //导致这些线程处于等待的状态,无法继续执行就会出现死锁

        //创建两个锁对象
        Object o1 = new Object();
        Object o2 = new Object();
        //使用匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (o1){
                        synchronized (o2){
                            System.out.println("o1 锁 o2");
                        }
                    }
                }

            }
        }).start();   new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (o2){
                        synchronized (o1){
                            System.out.println("o2 锁 o1");
                        }
                    }
                }

            }
        }).start();
    }
}
class Piao extends Thread{
    private  int ticket=100;
    private Object obj=new Object();
    private ReentrantLock lock=new ReentrantLock();

      //同步代码块   锁加在操作共享数据的代码上  锁对象唯一
//    @Override
//    public void run() {
//        while (true){
//            synchronized (obj){
//                if (ticket>0){
//                    try {
//                        Thread.sleep(200);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    //获取线程名称
//                    System.out.println(Thread.currentThread().getName()+"卖出票号:"+ticket+"号");
//                    ticket--;
//                }else{
//                    break;
//                }
//            }
//
//        }
//    }

    //同步方法
//    @Override
//    public void run() {
//        while (true){
//            method();
//            if (ticket<=0){
//                break;
//            }
//        }
//    }
//    private void method() {
//        if (ticket>0){
//            System.out.println(Thread.currentThread().getName()+"卖出票号:"+ticket+"号");
//            ticket--;
//        }
//    }

    //lock锁  锁加在操作共享数据的代码上  锁对象唯一
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //加锁
            lock.lock();
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出票号:" + ticket + "号");
                ticket--;
            }
            //释放锁对象
            lock.unlock();
            if (ticket<=0){
                break;
            }
        }
    }
}